package com.ssy.lingxi.member.merchant.serviceimpl.feign;

import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.MemberRelationDO;
import com.ssy.lingxi.member.merchant.model.bo.AuthBO;
import com.ssy.lingxi.member.merchant.model.bo.WorkflowTaskListBO;
import com.ssy.lingxi.member.merchant.model.bo.WorkflowTaskResultBO;
import com.ssy.lingxi.member.merchant.model.vo.validate.response.WorkFlowStepVO;
import com.ssy.lingxi.member.merchant.service.feign.IWorkflowFeignService;
import com.ssy.lingxi.workflow.api.feign.ProcessFeign;
import com.ssy.lingxi.workflow.api.feign.ProcessMemberRoleControllerFeign;
import com.ssy.lingxi.workflow.api.model.vo.request.*;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleProcessDefVO;
import com.ssy.lingxi.workflow.api.model.vo.response.SimpleTaskCompleteVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 调用工作流服务Feign接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2020-09-14
 */
@Service
public class WorkflowFeignServiceImpl implements IWorkflowFeignService {
    private static final Logger logger = LoggerFactory.getLogger(WorkflowFeignServiceImpl.class);

    @Resource
    private ProcessFeign processFeign;

    @Resource
    private ProcessMemberRoleControllerFeign processMemberRoleControllerFeign;

    /**
     * 启动会员流程
     *
     * @param relationDO 会员关系
     * @return 启动结果
     */
    @Override
    public Wrapper<WorkflowTaskResultBO> startMemberProcess(MemberRelationDO relationDO) {
        return startMemberProcess(relationDO.getValidateTask().getProcessKey(), relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getId());
    }

    /**
     * 启动会员入库、资料变更流程
     *
     * @param processKey 流程的Key
     * @param memberId   执行流程的会员Id
     * @param roleId     执行流程的会员角色Id
     * @param dataId     审核数据Id
     * @return 启动结果
     */
    @Override
    public Wrapper<WorkflowTaskResultBO> startMemberProcess(String processKey, Long memberId, Long roleId, Long dataId) {
        TaskStartVO startVO = new TaskStartVO();
        startVO.setProcessKey(processKey);
        startVO.setMemberId(memberId);
        startVO.setRoleId(roleId);
        startVO.setDataId(dataId);
        Wrapper<SimpleTaskCompleteVO> result;
        try {
            result = processFeign.startSimpleProcess(startVO);
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                return Wrapper.fail(result.getCode(), result.getMessage());
            }
        } catch (Exception e) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_WORKFLOW_ERROR);
        }

        return Wrapper.success(new WorkflowTaskResultBO(result.getData().getTaskId(), result.getData().getStatus(), result.getData().getProperties().getOrDefault("oper", "")));
    }

    /**
     * 执行会员流程
     *
     * @param relationDO 会员关系
     * @param agree      审核意见
     * @return 执行结果
     */
    @Override
    public Wrapper<WorkflowTaskResultBO> execMemberProcess(MemberRelationDO relationDO, Integer agree) {
        return execMemberProcess(relationDO.getValidateTask().getProcessKey(), relationDO.getValidateTask().getTaskId(), relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getId(), agree);
    }

    /**
     * 执行会员入库、资料变更流程
     *
     * @param processKey 流程的Key
     * @param taskId     流程任务Id
     * @param memberId   执行流程的会员Id
     * @param roleId     执行流程的会员角色Id
     * @param dataId     审核数据Id
     * @param agree      审核结果
     * @return 启动结果
     */
    @Override
    public Wrapper<WorkflowTaskResultBO> execMemberProcess(String processKey, String taskId, Long memberId, Long roleId, Long dataId, Integer agree) {
        TaskExecuteVO executeVO = new TaskExecuteVO();
        executeVO.setProcessKey(processKey);
        executeVO.setMemberId(memberId);
        executeVO.setRoleId(roleId);
        executeVO.setDataId(dataId);
        executeVO.setTaskId(taskId);
        executeVO.setAgree(agree);
        Wrapper<SimpleTaskCompleteVO> result;
        try {
            result = processFeign.completeSimpleTask(executeVO);
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                return Wrapper.fail(result.getCode(), result.getMessage());
            }
        } catch (Exception e) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_WORKFLOW_ERROR);
        }

        return Wrapper.success(new WorkflowTaskResultBO(result.getData().getTaskId(), result.getData().getStatus(), result.getData().getProperties().getOrDefault("oper", "")));
    }

    /**
     * 查询会员流程步骤
     *
     * @param relationDO 会员关系
     * @return 查询结果
     */
    @Override
    public Wrapper<WorkflowTaskListBO> listMemberProcessSteps(MemberRelationDO relationDO) {
        return listMemberProcessSteps(relationDO.getMemberId(), relationDO.getValidateTask().getProcessKey(), relationDO.getValidateTask().getTaskId());
    }

    /**
     * 查询会员入库审核步骤
     * @param memberId        执行流程的会员Id
     * @param processKey      流程的ProcessKey
     * @param taskId          将要执行的工作流任务Id
     * @return 查询结果
     */
    @Override
    public Wrapper<WorkflowTaskListBO> listMemberProcessSteps(Long memberId, String processKey, String taskId) {
        //如果是“无需审核”流程（空流程），直接返回
        if(processKey.equals(ServiceConfig.EMPTY_PLATFORM_VALIDATE_PROCESS_KEY) || processKey.equals(ServiceConfig.EMPTY_DEPOSITORY_PROCESS_KEY)) {
            return Wrapper.success(new WorkflowTaskListBO());
        }

        InternalProcessQueryVO queryVO = new InternalProcessQueryVO();
        queryVO.setProcessKey(processKey);
        queryVO.setMemberId(memberId);
        queryVO.setTaskId(taskId);

        Wrapper<SimpleProcessDefVO> result;
        try {
            result = processFeign.findSimpleInternalTaskDefinitions(queryVO);
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                return Wrapper.fail(result.getCode(), result.getMessage());
            }

            return Wrapper.success(new WorkflowTaskListBO(result.getData().getCurrentStep(), result.getData().getTasks().stream().map(task -> {
                WorkFlowStepVO stepVO = new WorkFlowStepVO();
                stepVO.setStep(task.getTaskStep());
                stepVO.setStepName(task.getTaskName());
                stepVO.setRoleName(task.getRoleName());
                return stepVO;
            }).sorted(Comparator.comparingInt(WorkFlowStepVO::getStep)).collect(Collectors.toList())));
        } catch (Exception e) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_WORKFLOW_ERROR);
        }
    }

    /**
     * 查询外部流程步骤
     * @param roleId 上级角色id
     * @param subRoleId 下级角色id
     * @param processKey 流程的ProcessKey
     * @param taskId 将要执行的工作流任务id
     * @return 查询结果
     */
    @Override
    public Wrapper<WorkflowTaskListBO> listExternalProcessSteps(Long roleId, Long subRoleId, String processKey, String taskId) {
        ExternalProcessQueryVO queryVO = new ExternalProcessQueryVO();
        queryVO.setProcessKey(processKey);
        queryVO.setRoleId(roleId);
        queryVO.setSubRoleId(subRoleId);
        queryVO.setTaskId(taskId);

        Wrapper<SimpleProcessDefVO> result;
        try {
            result = processFeign.findSimpleExternalTaskDefinitions(queryVO);
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                return Wrapper.fail(result.getCode(), result.getMessage());
            }

            return Wrapper.success(new WorkflowTaskListBO(result.getData().getCurrentStep(), result.getData().getTasks().stream().map(task -> {
                WorkFlowStepVO stepVO = new WorkFlowStepVO();
                stepVO.setStep(task.getTaskStep());
                stepVO.setStepName(task.getTaskName());
                stepVO.setRoleName(task.getRoleName());
                return stepVO;
            }).sorted(Comparator.comparingInt(WorkFlowStepVO::getStep)).collect(Collectors.toList())));
        } catch (Exception e) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_VALIDATE_WORKFLOW_ERROR);
        }
    }

    /**
     * 新增或修改会员角色时，关联工作流步骤
     * @param memberId       会员Id
     * @param memberRoleId   会员自定义角色Id
     * @param memberRoleName 会员自定义角色名称
     * @param authBOList     会员自定义角色权限列表
     */
    @Async
    @Override
    public void upsertMemberRoleToProcessAsync(Long memberId, Long memberRoleId, String memberRoleName, List<AuthBO> authBOList) {
        try {
            if (CollectionUtils.isEmpty(authBOList)) {
                Wrapper.success();
                return;
            }

            List<AuthUrlVO> accessUrls = authBOList.stream().map(authBO -> new AuthUrlVO(authBO.getUrl(), authBO.getSource())).collect(Collectors.toList());

            ProcessMemberRoleVO memberRoleVO = new ProcessMemberRoleVO();
            memberRoleVO.setMemberId(memberId);
            memberRoleVO.setMemberRoleId(memberRoleId);
            memberRoleVO.setMemberRoleName(memberRoleName);
            memberRoleVO.setUrls(accessUrls);
            Wrapper<Void> result = processMemberRoleControllerFeign.updateInsertProcessAsync(memberRoleVO);
            if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
                logger.error("通知工作流服务关联会员自定义角色错误：" + result.getMessage());
            }
        } catch (Exception e) {
            logger.error("通知工作流服务关联会员自定义角色错误", e);
        }
    }


    /**
     * 删除会员角色时，从关联的工作流步骤中移除会员角色
     * @param memberId     会员Id
     * @param memberRoleId 会员自定义角色Id
     */
    @Async
    @Override
    public void removeMemberRoleInProcessAsync(Long memberId, Long memberRoleId) {
        try {
            ProcessRemoveMemberRoleVO removeMemberRoleVO = new ProcessRemoveMemberRoleVO();
            removeMemberRoleVO.setMemberId(memberId);
            removeMemberRoleVO.setMemberRoleId(memberRoleId);
            processMemberRoleControllerFeign.removeMemberRoleAsync(removeMemberRoleVO);
        } catch (Exception e) {
            logger.error("通知工作流服务移除会员自定义角色错误", e);
        }
    }
}
